<template>
  <!-- 查询表单 card -->
  <SearchForm v-if="showSearch" :search="search" :reset="reset" :columns="searchColumns" :search-param="searchParam">
    <template #searchColumn>
      <slot name="searchColumn" :search-param="searchParam"></slot>
    </template>
  </SearchForm>

  <!-- 表格内容 card -->
  <div class="card table-main">
    <!-- 表格头部 操作按钮 -->
    <div class="table-header">
      <div class="header-button-lf">
        <slot name="header" :selected-list-ids="selectedListIds" :selected-list="selectedList" :is-selected="isSelected" />
      </div>
      <div v-if="toolButton" class="header-button-ri">
        <slot name="toolButton">
          <span class="setting">
            <FoldSetting @click="toggleExpandAll(tableData, false)" />
          </span>
          <span class="setting">
            <ExpandSetting @click="toggleExpandAll(tableData, true)" />
          </span>
        </slot>
      </div>
    </div>
    <!-- 表格主体 -->
    <ElTable
      ref="tableRef"
      v-bind="$attrs"
      :data="data ?? tableData"
      :border="border"
      :row-key="rowKey"
      @selection-change="selectionChange"
    >
      <!-- 默认插槽 -->
      <slot></slot>
      <template v-for="item in tableColumns" :key="item">
        <TableColumn :column="item">
          <template v-for="slot in Object.keys($slots)" #[slot]="scope">
            <slot :name="slot" :row="scope.row" :id="scope.row[props.rowKey]"></slot>
          </template>
        </TableColumn>
      </template>
      <!-- 插入表格最后一行之后的插槽 -->
      <template #append>
        <slot name="append"> </slot>
      </template>
      <!-- 无数据 -->
      <template #empty>
        <div class="table-empty">
          <slot name="empty">
            <img src="@/assets/images/notData.png" alt="notData" />
            <div>暂无数据</div>
          </slot>
        </div>
      </template>
    </ElTable>
    <!-- 分页组件 -->
    <slot name="pagination">
      <Pagination
        v-if="pagination"
        :pageable="pageable"
        :handle-size-change="handleSizeChange"
        :handle-current-change="handleCurrentChange"
      />
    </slot>
  </div>
</template>

<script setup lang="ts" name="Table">
import { ref, watch, onMounted, PropType, computed } from "vue";
import { ElTable } from "element-plus";
import { useTable } from "@/hooks/useTable";
import { useSelection } from "@/hooks/useSelection";
import { ColumnProps } from "../../type";
import SearchForm from "../SearchForm/index.vue";
import Pagination from "../Pagination/index.vue";
import FoldSetting from "../FoldSetting/index.vue";
import ExpandSetting from "../ExpandSetting/index.vue";
import TableColumn from "../TableColumn/index.vue";

const props = defineProps({
  columns: {
    type: Object as PropType<Array<ColumnProps>>
  },
  data: {
    type: Object as PropType<Array<any>>
  },
  requestApi: {
    type: Function
  },
  showSearch: {
    type: Boolean,
    default: true
  },
  requestAuto: {
    type: Boolean,
    default: true
  },
  pagination: {
    type: Boolean,
    default: true
  },
  initParam: {
    type: Object
  },
  border: {
    type: Boolean,
    default: true
  },
  toolButton: {
    type: Boolean,
    default: false
  },
  rowKey: {
    type: String,
    default: "id"
  }
});

// 表格 DOM 元素
const tableRef = ref<InstanceType<typeof ElTable>>();

// 表格多选 Hooks
const { selectionChange, selectedList, selectedListIds, isSelected } = useSelection(props.rowKey);

// 表格操作 Hooks
const { tableData, pageable, searchParam, searchInitParam, getTableList, search, reset, handleSizeChange, handleCurrentChange } =
  useTable(props.requestApi, props.initParam, props.pagination);

// 清空选中数据列表
const clearSelection = () => tableRef.value!.clearSelection();

// 初始化请求
onMounted(() => props.requestAuto && search());

// 监听页面 initParam 改化，重新获取表格数据
watch(() => props.initParam, search, { deep: true });

// 接收 columns 并设置为响应式
const tableColumns = computed(() => props.columns);

const toggleExpandAll = (tableData, status: Boolean) => {
  if (tableData && tableData.length > 0) {
    for (const data of tableData) {
      tableRef.value?.toggleRowExpansion(data, status);
      toggleExpandAll(data.children, status);
    }
  }
};
const toggleRowSelection = (row, selected: boolean) => {
  tableRef.value?.toggleRowSelection(row, selected);
};
// 过滤需要搜索的配置项
const searchColumns = computed(() =>
  props.columns!.filter(item => item.search?.el || item.search?.render).sort((a, b) => a.search!.order! - b.search!.order!)
);

// 暴露给父组件的参数和方法(外部需要什么，都可以从这里暴露出去)
defineExpose({
  element: tableRef,
  tableData,
  pageable,
  searchParam,
  searchInitParam,
  getTableList,
  search,
  reset,
  toggleRowSelection,
  handleSizeChange,
  handleCurrentChange,
  clearSelection,
  isSelected,
  selectedList,
  selectedListIds
});
</script>
<style scoped>
.setting {
  margin-left: 5px;
}
</style>
